/**
 * Created by lional on 16/10/2.
 *
 * RichText
 * format sample 格式例子:
 * "<a fontName='Arial' boundingWidth='10' boundingHeight='10' lineHeight='2' color='#00ff00' fontSize='36' textAlign='TEXT_ALIGNMENT_RIGHT' strokeEnabled='true' strokeStyle='#000000' lineWidth='2' shadowEnabled='true' shadowOffsetX='2' shadowOffsetY='-2' shadowBlur='4' fontWeight='#ffffff'> hello world! </a>"
 * "<a fontName='Arial' fontSize='24'>test line 1 \n test line 2 <br></br> test line 3</a>"
 * 参数说明:
 * 富文本支持xml格式,属性写在元素里面,如fontName,fontSize.类似web的document
 * \n和<br></br>都表示换行,选其一即可
 * 参数支持如下
 * fontName         字体名称
 * fontSize         字体尺寸
 * color            字体颜色
 * textAlign        文本的水平对齐方式。可选值有 TEXT_ALIGNMENT_LEFT，TEXT_ALIGNMENT_CENTER 和 TEXT_ALIGNMENT_RIGHT。
 * verticalAlign    文本的垂直对齐方式。可选值有 VERTICAL_TEXT_ALIGNMENT_TOP，VERTICAL_TEXT_ALIGNMENT_CENTER 和 VERTICAL_TEXT_ALIGNMENT_BOTTOM。
 * boundingWidth    文字整体宽度
 * boundingHeight   文字整体高度
 * lineHeight       文本的行高。
 * strokeEnabled    启用描边
 * strokeStyle      normal： 指定文本字体样式为正常的字体； bold:  指定文本字体样式为粗体的字体； italic： 指定文本字体样式为斜体。对于没有斜体变量的特殊字体，将应用oblique； oblique： 指定文本字体样式为倾斜的字体
 * lineWidth        描边像素粗细
 * shadowEnabled    阴影,下划线
 *
 * RichText.setString(text) 设置或者重置富文本
 * RichText.appendString(text) 追加富文本
 * RichText.prependString(text) 从头插入富文本
 * RichText.pollString(isTop) 删除一条富文本 是否从头删除
 *
 * 插入图片例子：
 * "<img src='res/Item_IMG_40/item_1.png' color='#ff0000' opacity='50'></img>"
 * 参数说明:
 * color            图片颜色，默认#ffffff
 * opacity          图片透明度
 * src              图片路径
 */

jGame.RichElement = ccui.RichElement.extend(/** @lends jGame.RichElement# */{

    ctor: function () {
        this._super();
        //cc.log("jGame.RichElement#ctor()");
    },

});

jGame.RichElementText = ccui.RichElementText.extend(/** @lends jGame.RichElementText# */{

    ctor: function (tag, colorOrFontDef, opacity, text, fontName, fontSize) {
        this._super(tag, colorOrFontDef, opacity, text, fontName, fontSize);
        //cc.log("jGame.RichElementText#ctor()");
    },

});

jGame.RichElementImage = ccui.RichElementImage.extend(/** @lends jGame.RichElementImage# */{

    ctor: function (tag, color, opacity, filePath) {
        this._super(tag, color, opacity, filePath);
        //cc.log("jGame.RichElementImage#ctor()");
    },

});

jGame.RichElementCustomNode = ccui.RichElementCustomNode.extend(/** @lends jGame.RichElementCustomNode# */{

    ctor: function (tag, color, opacity, customNode) {
        this._super(tag, color, opacity, customNode);
        //cc.log("jGame.RichElementCustomNode#ctor()");
    },

});

jGame.RichElementTypingText = ccui.RichElementCustomNode.extend(/** @lends jGame.RichElementText# */{

    _text: null,
    _label: null,
    _speed: null,
    _endCallback: null,
    _isPlaying: null,
    _action: null,

    ctor: function (tag, color, opacity, jGameText) {
        this._label = jGameText;
        this._text = jGameText.getString();
        this._speed = 30;
        this._super(tag, color, opacity, jGameText);
        //cc.log("jGame.RichElementTypingText#ctor(" + this._text + ")");
    },

    setTypewriter: function (isTypingText) {
        if(isTypingText) {
            this._label.setString("");
        }
    },

    play: function (endCallback) {
        this._isPlaying = true;
        this._endCallback = endCallback;
        if(this._label)this._label.setString("");
        var that = this;
        var tempArray = [];
        for(var i = 1; i <= this._text.length; i++) {
            var ticketCallBack = function (sender, num) {
                if(that._isPlaying) {
                    if(num == that._text.length) {
                        if(that._label)that._label.setString(that._text);
                        that._isPlaying = false;
                        if(that._endCallback && typeof that._endCallback == "function") {
                            that._endCallback();
                        }
                    }else {
                        var text = that._text.substr(0, num);
                        if(that._label)that._label.setString(text);
                    }
                }
            }
            tempArray.push(cc.delayTime(this._speed/1000));
            tempArray.push(cc.callFunc(ticketCallBack, this._label, i));
        }
        this._action = cc.sequence(tempArray);
        if(this._action) {
            app.getRunningScene().runAction(this._action);
        }else {
            if(that._label)that._label.setString(that._text);
            that._isPlaying = false;
            if(that._endCallback && typeof that._endCallback == "function") {
                that._endCallback();
            }
        }
    },

    stop: function () {
        if(this._isPlaying) {
            this._isPlaying = false;
            app.getRunningScene().stopAction(this._action);
            if(this._label)this._label.setString(this._text);
        }
    },

    getPercent: function () {
        if(this._text && this._label) {
            return this._label.getString().length * 100 / this._text.length;
        }
        return 100;
    }

});

jGame.RichText = ccui.RichText.extend(/** @lends jGame.RichText# */{

    _parser: null,
    _attributes: null,
    _texts: null,
    _textElementMap: null,
    _jGameRichElements: null,
    _parserElementsIndex: null,
    _initWidth: null,
    _isTypingText: null,
    _isTypingEndCallback: null,
    _isTyping: null,
    _isDoTypingAnim: null,
    _isPrepend: false,
    _lastWidth: null,

    ctor: function (xml) {
        this._super();
        //cc.log("jGame.RichText#ctor(" + xml + ")");
        this._parser = new jGame.SaxParser(this);
        this._attributes = [];
        this._texts = [];
        this._textElementMap = [];
        this._jGameRichElements = [];
        this.setString(xml);
        this._texts.length = 0;
        this._lastWidth = 0;
    },

    onExit: function () {
        this._super();
        //cc.log("jGame.RichText[" + this.name + "]#onExit()");
    },

    onStartDocument: function () {
        //cc.log("onStartDocument");
        if(this._texts.length > 0) {
            this._textElementMap[this._texts.length - 1] = 0;
            if(this._jGameRichElements.length > 0) {
                this._textElementMap[this._texts.length - 1] = this._jGameRichElements.length;
            }
        }
    },

    onEndDocument: function () {
        //cc.log("onEndDocument");
        this.formatText();
        if(!this.isIgnoreContentAdaptWithSize()) {
            this.setContentSize(this.getRendererSize());
        }
        if(this._texts.length > 0) {
            this._textElementMap[this._texts.length - 1] = this._jGameRichElements.length - this._textElementMap[this._texts.length - 1];
            if(this._isPrepend) {
                var last = this._textElementMap[this._textElementMap.length - 1];
                this._textElementMap.length = this._textElementMap.length -1;
                this._textElementMap.splice(0,0,last);
            }
        }
    },

    onStartElementNS: function (elem, attrs, prefix, uri, namespaces) {
        //cc.log("=> Started: " + elem + " uri="+uri +" (Attributes: " + JSON.stringify(attrs) + " )");
        var attribute = {};
        for(var index in attrs) {
            var arr = attrs[index];
            if(arr && arr instanceof Array) {
                if(arr.length > 0) {
                    attribute[arr[0]] = arr[1];
                }
            }
        }
        this._initWidth = parseFloat(attribute["width"]) >= 0?attribute["width"]:this._initWidth;

        this._pushAttribute({"elem":elem, "attrs":attribute, "prefix":prefix, "uri":uri, "namespaces":namespaces})
    },

    onEndElementNS: function (elem, prefix, uri) {
        //cc.log("<= End: " + elem + " uri="+uri + "\n");
        var attribute = this._getAttribute();
        var elem = attribute["elem"];
        var attrs = attribute["attrs"];
        if(parseFloat(attrs["anchorX"]) >= 0) {
            var richText = this;
            setTimeout(function () {
                richText.anchorX = parseFloat(attrs["anchorX"]);
            }, 0);
        }
        if(parseFloat(attrs["anchorY"]) >= 0) {
            var richText = this;
            setTimeout(function () {
                richText.anchorY = parseFloat(attrs["anchorY"]);
            }, 0);
        }
        if(parseFloat(attrs["width"]) >= 0) {
            var richText = this;
            setTimeout(function () {
                richText.width = parseFloat(attrs["width"]);
                richText.ignoreContentAdaptWithSize(false);
            }, 0);
        }
        if(elem == "br") {
            var element = new jGame.RichElementText(this._jGameRichElements.length, cc.color(), 255, "\n", "Arial", 10);
            if(this._isPrepend) {
                this._jGameRichElements.splice(0,0,element);
                this.pushTopElement(element);
            }else {
                this._jGameRichElements.push(element);
                this.pushBackElement(element);
            }
        }else if(elem == "img" || elem == "ImageView") {
            var opacity = parseInt(attrs["opacity"])>=0?parseInt(attrs["opacity"])*2.55:255;
            var color = attrs["color"]?cc.hexToColor(attrs["color"]):cc.color();color.a = opacity;
            var filePath = attrs["src"]?attrs["src"]:"";
            if(filePath) {
                var element = new jGame.RichElementImage(this._jGameRichElements.length, color, opacity, filePath);
                if(this._isPrepend) {
                    this._jGameRichElements.splice(0,0,element);
                    this.pushTopElement(element);
                }else {
                    this._jGameRichElements.push(element);
                    this.pushBackElement(element);
                }
            }
        }else if(elem == "node" || elem == "Node") {
            //todo
        }
        this._popAttribute();
    },

    onCharacters: function (chars) {
        //cc.log(JSON.stringify(this._getAttribute()));
        //cc.log('<CHARS>'+chars+"</CHARS>");
        var attribute = this._getAttribute();
        var elem = attribute["elem"];
        var attrs = attribute["attrs"];
        if(elem != "img" && elem != "node" && elem != "ImageView" && elem != "Node") {
            /*
             FontDefinition.fontName = "Arial";
             FontDefinition.fontSize = 12;
             FontDefinition.textAlign = cc.TEXT_ALIGNMENT_CENTER;
             FontDefinition.verticalAlign = cc.VERTICAL_TEXT_ALIGNMENT_TOP;
             FontDefinition.color = cc.color(255, 255, 255, 255);
             FontDefinition.boundingWidth = 0;
             FontDefinition.boundingHeight = 0;

             FontDefinition.strokeEnabled = false;
             FontDefinition.strokeStyle = cc.color(255, 255, 255, 255);(strokeOpacity)
             FontDefinition.lineWidth = 1;
             FontDefinition.lineHeight = "normal";
             FontDefinition.fontStyle = "normal";
             FontDefinition.fontWeight = "normal";

             FontDefinition.shadowEnabled = false;
             FontDefinition.shadowOffsetX = 0;
             FontDefinition.shadowOffsetY = 0;
             FontDefinition.shadowBlur = 0;
             FontDefinition.shadowOpacity = 1.0;
             */
            var fontName = attrs["fontName"]?attrs["fontName"]:"Arial";
            var fontSize = parseInt(attrs["fontSize"])>=0?parseInt(attrs["fontSize"]):24;
            var textAlign = cc[attrs["textAlign"]] == cc.TEXT_ALIGNMENT_LEFT || cc[attrs["textAlign"]] == cc.TEXT_ALIGNMENT_CENTER || cc[attrs["textAlign"]] == cc.TEXT_ALIGNMENT_RIGHT ?cc[attrs["textAlign"]]:cc.TEXT_ALIGNMENT_LEFT;
            var verticalAlign = cc[attrs["verticalAlign"]] == cc.VERTICAL_TEXT_ALIGNMENT_TOP || cc[attrs["verticalAlign"]] == cc.VERTICAL_TEXT_ALIGNMENT_CENTER || cc[attrs["verticalAlign"]] == cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM?cc[attrs["verticalAlign"]]:cc.VERTICAL_TEXT_ALIGNMENT_TOP;
            var opacity = parseInt(attrs["opacity"])>=0?parseInt(attrs["opacity"])*2.55:255;
            var fillStyle = attrs["color"]?cc.hexToColor(attrs["color"]):cc.color();fillStyle.a = opacity;
            var boundingWidth = parseInt(attrs["boundingWidth"])>=0?parseInt(attrs["boundingWidth"]):0;
            var boundingHeight = parseInt(attrs["boundingHeight"])>=0?parseInt(attrs["boundingHeight"]):0;

            var strokeEnabled = attrs["strokeEnabled"] == "true";
            var strokeOpacity = parseInt(attrs["strokeOpacity"])>=0?parseInt(attrs["strokeOpacity"])*2.55:255;
            var strokeStyle = attrs["strokeStyle"]?cc.hexToColor(attrs["strokeStyle"]):cc.color();strokeStyle.a = strokeOpacity;
            var lineWidth = parseInt(attrs["lineWidth"])>=0?parseInt(attrs["lineWidth"]):1;
            var lineHeight = parseInt(attrs["lineHeight"])>=0?parseInt(attrs["lineHeight"]):14;
            /*normal： 指定文本字体样式为正常的字体； bold:  指定文本字体样式为粗体的字体； italic： 指定文本字体样式为斜体。对于没有斜体变量的特殊字体，将应用oblique； oblique： 指定文本字体样式为倾斜的字体  */
            var fontStyle = attrs["fontStyle"]?attrs["fontStyle"]:"normal";
            var fontWeight = attrs["fontWeight"]?attrs["fontWeight"]:"normal";

            var shadowEnabled = attrs["shadowEnabled"] == "true";
            var shadowOffsetX = parseInt(attrs["shadowOffsetX"])>=0?parseInt(attrs["shadowOffsetX"]):0;
            var shadowOffsetY = parseInt(attrs["shadowOffsetY"])>=0?parseInt(attrs["shadowOffsetY"]):0;
            var shadowBlur = parseInt(attrs["shadowBlur"])>=0?parseInt(attrs["shadowBlur"]):0;
            var shadowOpacity = parseInt(attrs["shadowOpacity"])>=0?parseInt(attrs["shadowOpacity"])/100:1.0;
            var shadowStyle = attrs["shadowStyle"]?attrs["shadowStyle"]:null;

            var fontDefinition = new cc.FontDefinition();
            fontDefinition.fontName = fontName
            fontDefinition.fontSize = fontSize
            fontDefinition.textAlign = textAlign
            fontDefinition.verticalAlign = verticalAlign
            fontDefinition.fillStyle = fillStyle
            fontDefinition.boundingWidth = boundingWidth
            fontDefinition.boundingHeight = boundingHeight
            fontDefinition.fontStyle = fontStyle

            fontDefinition.strokeEnabled = strokeEnabled
            fontDefinition.strokeStyle = strokeStyle
            fontDefinition.lineWidth = lineWidth
            fontDefinition.lineHeight = lineHeight

            fontDefinition.shadowEnabled = shadowEnabled
            fontDefinition.shadowOffsetX = shadowOffsetX
            fontDefinition.shadowOffsetY = shadowOffsetY
            fontDefinition.shadowBlur = shadowBlur
            fontDefinition.shadowOpacity = shadowOpacity
            fontDefinition.fontWeight = shadowStyle

            //var element = new jGame.RichElementText(this._jGameRichElements.length, fontDefinition, opacity, chars, fontName, fontSize);
            //var element = new jGame.RichElementText(this._jGameRichElements.length, fillStyle, opacity, chars, fontName, fontSize);
            var text = new jGame.Text(chars, fontDefinition);
            text.setAnchorPoint(this.getAnchorPoint());
            var panelWidth = parseFloat(this._initWidth) >= 0? parseFloat(this._initWidth):this.width;
            if(panelWidth > 0 && text.width+this._lastWidth > panelWidth) {
                var i = 1;
                var headText = new jGame.Text(chars.substr(0,i), fontDefinition);
                headText.setAnchorPoint(this.getAnchorPoint());
                while (headText.width+this._lastWidth <= panelWidth) {
                    i++;
                    headText = new jGame.Text(chars.substr(0,i), fontDefinition);
                    headText.setAnchorPoint(this.getAnchorPoint());
                }
                i--;
                headText = new jGame.Text(chars.substr(0,i), fontDefinition);
                headText.setAnchorPoint(this.getAnchorPoint());
                headText.ignoreContentAdaptWithSize(false);
                var element = new jGame.RichElementTypingText(this._jGameRichElements.length, cc.color.WHITE, 255, headText);
                element.setTypewriter(this._isTypingText && this._isDoTypingAnim);
                if(this._isPrepend) {
                    this._jGameRichElements.splice(0,0,element);
                    this.pushTopElement(element);
                }else {
                    this._jGameRichElements.push(element);
                    this.pushBackElement(element);
                }

                var end_chars = chars.substr(i, chars.length - i);
                var text = new jGame.Text(end_chars, fontDefinition);
                text.setAnchorPoint(this.getAnchorPoint());
                if(text.width > panelWidth) {
                    i = 1;
                    while (i >= end_chars.length) {
                        var middleText = new jGame.Text(end_chars.substr(0,i), fontDefinition);
                        middleText.setAnchorPoint(this.getAnchorPoint());
                        if(middleText.width > panelWidth) {
                            i--;
                            var middleText = new jGame.Text(end_chars.substr(0,i), fontDefinition);
                            middleText.setAnchorPoint(this.getAnchorPoint());
                            middleText.ignoreContentAdaptWithSize(false);
                            var element = new jGame.RichElementTypingText(this._jGameRichElements.length, cc.color.WHITE, 255, middleText);
                            element.setTypewriter(this._isTypingText && this._isDoTypingAnim);
                            if(this._isPrepend) {
                                this._jGameRichElements.splice(0,0,element);
                                this.pushTopElement(element);
                            }else {
                                this._jGameRichElements.push(element);
                                this.pushBackElement(element);
                            }
                            end_chars = end_chars.substr(i, end_chars.length - i);
                            i = 1;
                        }
                        i++;
                    }
                    var text = new jGame.Text(end_chars, fontDefinition);
                    text.setAnchorPoint(this.getAnchorPoint());
                    this._lastWidth = text.width;
                    text.ignoreContentAdaptWithSize(false);
                    if(textAlign != cc.TEXT_ALIGNMENT_LEFT)text.width = panelWidth;
                }else {
                    this._lastWidth = text.width;
                    text.ignoreContentAdaptWithSize(false);
                    if(textAlign != cc.TEXT_ALIGNMENT_LEFT)text.width = panelWidth;
                }
            }else {
                this._lastWidth = this._lastWidth + text.width;
                text.ignoreContentAdaptWithSize(false);
                if(textAlign != cc.TEXT_ALIGNMENT_LEFT)text.width = panelWidth;
            }
            var element = new jGame.RichElementTypingText(this._jGameRichElements.length, cc.color.WHITE, 255, text);
            element.setTypewriter(this._isTypingText && this._isDoTypingAnim);
            if(this._isPrepend) {
                this._jGameRichElements.splice(0,0,element);
                this.pushTopElement(element);
            }else {
                this._jGameRichElements.push(element);
                this.pushBackElement(element);
            }
            if(this._isTypingText) {
                if(this._parserElementsIndex == null) {
                    this._parserElementsIndex = 0;
                    this.startParserElements(this._isDoTypingAnim);
                }else if(!this.isParserElements()) {
                    this.startParserElements(this._isDoTypingAnim);
                }
            }
        }
    },

    onCdata: function (cdata) {
        //cc.log('<CDATA>'+cdata+"</CDATA>");
    },

    onComment: function (msg) {
        //cc.log('<COMMENT>'+msg+"</COMMENT>");
    },

    onWarning: function (msg) {
        cc.log('<WARNING>'+msg+"</WARNING>");
    },

    onError: function (msg) {
        cc.log('<ERROR>'+JSON.stringify(msg)+"</ERROR>");
    },

    /**
     * Push a attribute
     * @param {} attribute
     */
    _pushAttribute: function (attribute) {
        this._attributes.push(attribute);
    },

    /**
     * Poll a attribute
     * @param {} attribute
     */
    _popAttribute: function () {
        this._attributes.pop();
    },

    _getAttribute: function () {
        var i = this._attributes.length;
        if (i === 0) {
            return this._attributes[i];
        } else {
            return this._attributes[i - 1];
        }
    },

    getElementsCount: function () {
        return this._jGameRichElements.length;
    },

    /**
     * Changes the  value of jGame.RichText.
     * @param {String} text
     */
    setString: function (text, doAnim) {
        if(text === undefined)return;
        var rText = text;
        rText = rText.replace('\n', "<br></br>");
        if(rText.charAt(0) != "<" || rText.charAt(rText.length-1) != ">") {
            rText = "<a>" + rText + "</a>";
        }
        //reset elements
        for (var index in this._jGameRichElements) {
            var element = this._jGameRichElements[index];
            if(typeof element["stop"] === "function") {
                element["stop"]();
            }
            this.removeElement(element);
        }
        this._jGameRichElements.length = 0;
        this._texts.length = 0;
        this._attributes.length = 0;
        this._isDoTypingAnim = doAnim?true:false;
        this._isPrepend = false;
        this._texts.push(rText);
        this._parser = new jGame.SaxParser(this);
        this._parser.parseString(rText);
        this._lastWidth = 0;
    },

    appendString: function (text, doAnim) {
        if(text === undefined)return;
        var rText = text;
        rText = rText.replace('\n', "<br></br>");
        if(rText.charAt(0) != "<" || rText.charAt(rText.length-1) != ">") {
            rText = "<a>" + rText + "</a>";
        }
        this._attributes.length = 0;
        this._isDoTypingAnim = doAnim?true:false;
        this._isPrepend = false;
        this._texts.push(rText);
        this._parser = new jGame.SaxParser(this);
        this._parser.parseString(rText);
        this._lastWidth = 0;
    },

    prependString: function (text, doAnim) {
        if(text === undefined)return;
        var rText = text;
        rText = rText.replace('\n', "<br></br>");
        if(rText.charAt(0) != "<" || rText.charAt(rText.length-1) != ">") {
            rText = "<a>" + rText + "</a>";
        }
        this._attributes.length = 0;
        this._isDoTypingAnim = false;//不支持打印
        this._isPrepend = true;
        this._texts.splice(0,0,rText);
        this._parser = new jGame.SaxParser(this);
        this._parser.parseString(rText);
        this._lastWidth = 0;
    },

    pollString: function (isTop) {
        if(this._texts.length > 1) {
            var text;
            var length;
            var elements;
            if(isTop) {
                text = this._texts.splice(this._texts.length - 1, 1);
                var lengths = this._textElementMap.splice(this._textElementMap.length - 1, 1);
                length = lengths[0];
                elements = this._jGameRichElements.splice(this._jGameRichElements.length - length, length);
            }else {
                text = this._texts.splice(0,1);
                var lengths = this._textElementMap.splice(0,1);
                length = lengths[0];
                elements = this._jGameRichElements.splice(0,length);
            }
            //reset elements
            for (var index in elements) {
                var element = elements[index];
                if(typeof element["stop"] === "function") {
                    element["stop"]();
                }
                this.removeElement(element);
            }
            this._parserElementsIndex -= length;
            this.formatText();
            if(!this.isIgnoreContentAdaptWithSize()) {
                this.setContentSize(this.getRendererSize());
            }
        } else {
            for (var index in this._jGameRichElements) {
                var element = this._jGameRichElements[index];
                if(typeof element["stop"] === "function") {
                    element["stop"]();
                }
                this.removeElement(element);
            }
            this._jGameRichElements.length = 0;
            this._parserElementsIndex = null;
            this._isTyping = false;
            this._texts.length = 0;
            this._attributes.length = 0;
            this._isDoTypingAnim = false;
            this.formatText();
        }
    },

    setTypewriter: function (isTypingText, callback) {
        this._isTypingText = isTypingText?true:false;
        this._isTypingEndCallback = callback;
    },

    isParserElements: function () {
        return this._isTyping?true:false;
    },

    startParserElements: function (doAnim) {
        //cc.log("jGame.RichText#startParserElements[" + this._jGameRichElements.length + "] : " + this._parserElementsIndex + ", anim :" + doAnim);
        this._isTyping = true;
        if(doAnim && this._jGameRichElements && this._jGameRichElements[this._parserElementsIndex] && this._jGameRichElements[this._parserElementsIndex] instanceof jGame.RichElementTypingText) {
            var that = this;
            this._jGameRichElements[this._parserElementsIndex].play(function () {
                that._parserElementsIndex++;
                that.startParserElements(doAnim);
            });
        }else if(this._jGameRichElements && this._jGameRichElements[this._parserElementsIndex]) {
            this._parserElementsIndex++;
            this.startParserElements(doAnim);
        }else {
            //end
            //cc.log("jGame.RichText#endParserElements");
            this._isTyping = false;
            if(this._isDoTypingAnim && typeof this._isTypingEndCallback === "function"){
                this._isDoTypingAnim=false;
                this._isTypingEndCallback();
            }
        }
    },

    stopParserElements: function () {
        if(this._isTyping) {
            if(this._jGameRichElements && this._jGameRichElements[this._parserElementsIndex] && this._jGameRichElements[this._parserElementsIndex] instanceof jGame.RichElementTypingText) {
                this._jGameRichElements[this._parserElementsIndex].stop();
            }
            this.startParserElements(false);
        }
    },

    getStrings: function () {
        return this._texts;
    },

    getString: function () {
        var rText = "";
        for(var index in this._texts) {
            rText += this._texts[index];
        }
        return "<a>" + rText + "</a>";
    },

    pushTopElement: function (element) {
        this.insertElement(element, 0);
    },

});